#include <config.h>
#include <board.h>
#include <init.h>
#include <os.h>
#include "device.h"
#include "printk.h"

#include "settings.h"
#include "stm32_i2c.h"
#include <stm32f0xx.h>
#ifdef configUSING_I2C
/*
 * GPIO define
 */
#define GPIO_PORT_I2C1_SCL  GPIOB
#define RCC_I2C1_SCL      	RCC_AHBPeriph_GPIOB
#define PIN_I2C1_SCL      	GPIO_Pin_6

#define GPIO_PORT_I2C1_SDA  GPIOB
#define RCC_I2C1_SDA      	RCC_AHBPeriph_GPIOB
#define PIN_I2C1_SDA      	GPIO_Pin_7

#define GPIO_PORT_I2C2_SCL  GPIOB
#define RCC_I2C2_SCL      	RCC_AHBPeriph_GPIOB
#define PIN_I2C2_SCL      	GPIO_Pin_10

#define GPIO_PORT_I2C2_SDA  GPIOB
#define RCC_I2C2_SDA      	RCC_AHBPeriph_GPIOB
#define PIN_I2C2_SDA      	GPIO_Pin_11

static struct i2c_bus_device stm32_i2c1, stm32_i2c2;

#ifdef USING_I2C1
static void i2c1_set_sda(void *data, int32_t state)
{
    if (state)
    {
        GPIO_SetBits(GPIO_PORT_I2C1_SDA, PIN_I2C1_SDA);
    }
    else
    {
        GPIO_ResetBits(GPIO_PORT_I2C1_SDA, PIN_I2C1_SDA);
    }
}

static void i2c1_set_scl(void *data, int32_t state)
{
    if (state == 1)
    {
        GPIO_SetBits(GPIO_PORT_I2C1_SCL, PIN_I2C1_SCL);
    }
    else if (state == 0)
    {
        GPIO_ResetBits(GPIO_PORT_I2C1_SCL, PIN_I2C1_SCL);
    }
}

static int32_t i2c1_get_sda(void *data)
{
    return (int32_t)GPIO_ReadInputDataBit(GPIO_PORT_I2C1_SDA, PIN_I2C1_SDA);
}

static int32_t i2c1_get_scl(void *data)
{
    return (int32_t)GPIO_ReadInputDataBit(GPIO_PORT_I2C1_SCL, PIN_I2C1_SCL);
}

static const struct i2c_bit_ops stm32_i2c1_bit_ops =
{
    (void *)0xaa,
    i2c1_set_sda,
    i2c1_set_scl,
    i2c1_get_sda,
    i2c1_get_scl,
    board_udelay,
    100,
    5
};
#endif

#ifdef USING_I2C2
static void i2c2_set_sda(void *data, int32_t state)
{
    if (state)
    {
        GPIO_SetBits(GPIO_PORT_I2C2_SDA, PIN_I2C2_SDA);
    }
    else
    {
        GPIO_ResetBits(GPIO_PORT_I2C2_SDA, PIN_I2C2_SDA);
    }
}
static void i2c2_set_scl(void *data, int32_t state)
{
    if (state == 1)
    {
        GPIO_SetBits(GPIO_PORT_I2C2_SCL, PIN_I2C2_SCL);
    }
    else if (state == 0)
    {
        GPIO_ResetBits(GPIO_PORT_I2C2_SCL, PIN_I2C2_SCL);
    }
}

static int32_t i2c2_get_sda(void *data)
{
    return (int32_t)GPIO_ReadInputDataBit(GPIO_PORT_I2C2_SDA, PIN_I2C2_SDA);
}

static int32_t i2c2_get_scl(void *data)
{
    return (int32_t)GPIO_ReadInputDataBit(GPIO_PORT_I2C2_SCL, PIN_I2C2_SCL);
}

static const struct i2c_bit_ops stm32_i2c2_bit_ops =
{
    (void *)0xaa,
    i2c2_set_sda,
    i2c2_set_scl,
    i2c2_get_sda,
    i2c2_get_scl,
    board_udelay,
    20,
    5
};
#endif
static void RCC_Configuration(void)
{
    RCC_AHBPeriphClockCmd(RCC_I2C1_SCL | RCC_I2C1_SDA
						  | RCC_I2C2_SCL | RCC_I2C2_SDA, ENABLE);
}

static void GPIO_Configuration(void)
{
    GPIO_InitTypeDef  GPIO_InitStructure;

#ifdef USING_I2C1
    /* config I2C1 SCL PIN */
    GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_OUT;
    GPIO_InitStructure.GPIO_OType = GPIO_OType_OD;
    GPIO_InitStructure.GPIO_PuPd  = GPIO_PuPd_UP;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;

    GPIO_InitStructure.GPIO_Pin   = PIN_I2C1_SCL;
    GPIO_Init(GPIO_PORT_I2C1_SCL, &GPIO_InitStructure);
	GPIO_SetBits(GPIO_PORT_I2C1_SCL, PIN_I2C1_SCL);

    /* config I2C1 SDA PIN */
    GPIO_InitStructure.GPIO_Pin   = PIN_I2C1_SDA;
    GPIO_Init(GPIO_PORT_I2C1_SDA, &GPIO_InitStructure);
	GPIO_SetBits(GPIO_PORT_I2C1_SDA, PIN_I2C1_SDA);
#endif
    
#ifdef USING_I2C2
	/* config I2C2 SCL PIN */
    GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_OUT;
    GPIO_InitStructure.GPIO_OType = GPIO_OType_OD;
    GPIO_InitStructure.GPIO_PuPd  = GPIO_PuPd_UP;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;

    GPIO_InitStructure.GPIO_Pin   = PIN_I2C2_SCL;
    GPIO_Init(GPIO_PORT_I2C2_SCL, &GPIO_InitStructure);
	GPIO_SetBits(GPIO_PORT_I2C2_SCL, PIN_I2C2_SCL);

	/* config I2C2 SDA PIN */
    GPIO_InitStructure.GPIO_Pin   = PIN_I2C2_SDA;
    GPIO_Init(GPIO_PORT_I2C2_SDA, &GPIO_InitStructure);
	GPIO_SetBits(GPIO_PORT_I2C2_SDA, PIN_I2C2_SDA);
#endif
}

static int hw_i2c_init(void)
{
    RCC_Configuration();
    GPIO_Configuration();

#ifdef USING_I2C1
    stm32_i2c1.priv = (void *)&stm32_i2c1_bit_ops;
    i2c_bit_add_bus(&stm32_i2c1, "i2c1");
#endif

#ifdef USING_I2C2
	stm32_i2c2.priv = (void *)&stm32_i2c2_bit_ops;
    i2c_bit_add_bus(&stm32_i2c2, "i2c2");
#endif
    
    return 0;
}

device_initcall(hw_i2c_init);
#endif
